/*
 * Java CMPP API
 * Copyright (C) 1998 - 2002 by Xu Youming
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * A copy of the LGPL can be viewed at http://www.gnu.org/copyleft/lesser.html
 * Java CMPP API author: xuym@bc-info.net
 * Java CMPP API Homepage: http://cmppapi.sourceforge.net/
 * $Id: ReceiverExitEvent.java,v 1.1 2008/03/19 02:56:56 xym Exp $
 */

package com.bci.cmpp.event;

import com.bci.cmpp.Connection;

/**
 * Event generated by the receiver thread exiting. This event will be generated
 * when the receiver thread terminates either normally or abnormally due to an
 * exception. In the former case, isException will return false. In the latter,
 * isException will return true and the Throwable object that was the cause of
 * the thread's termination can be accessed using {@link #getException}. If an
 * application receives this event, it can be assumed that the connection to the
 * SMSG is invalid. That is, the network-specific connection will have to be
 * reestablished before binding to the SMSG is again possible. It is up to the
 * application to do any necessary clean up to the old network connection.
 * 
 * @author Xu Youming
 * @version 1.0
 */
public class ReceiverExitEvent extends CMPPEvent {
    /**
     * Recevier exit reason of "unknown".
     */
    public static final int UNKNOWN = 0;

    /**
     * Receiver exited because bind timed out.
     */
    public static final int BIND_TIMEOUT = 1;

    /**
     * Receiver exited due to an exception.
     */
    public static final int EXCEPTION = 2;

    /** The exception that caused thread termination. */
    private Throwable exception = null;

    /** The state the Connection was in when the thread exited. */
    private int connectionState = 0;

    /**
     * The reason for the exit.
     */
    private int reason = UNKNOWN;

    /**
     * Create a new ReceiverExitEvent. Events created with this constructor will
     * signify a normal receiver thread termination with no errors.
     * 
     * @param source
     *            the source Connection of this event.
     */
    public ReceiverExitEvent(Connection source) {
        super(RECEIVER_EXIT, source);
    }

    /**
     * Create a new ReceiverExitEvent. If <code>t</code> is not null, the
     * newly created event will represent an abnormal termination of the
     * receiver thread. If <code>t</code> is null, this constructor has the
     * same effect as {@link #ReceiverExitEvent(Connection)}.
     * 
     * @param source
     *            the source Connection of this event.
     * @param t
     *            the exception which caused termination (may be null).
     */
    public ReceiverExitEvent(Connection source, Throwable t) {
        super(RECEIVER_EXIT, source);
        setException(t);
    }

    /**
     * Create a new ReceiverExitEvent. If <code>t</code> is not null, the
     * newly created event will represent an abnormal termination of the
     * receiver thread. If <code>t</code> is null, this constructor has the
     * same effect as {@link #ReceiverExitEvent(Connection)}.
     * 
     * @param source
     *            the source Connection of this event.
     * @param t
     *            the exception which caused termination (may be null).
     * @param state
     *            the state the Connection was in when termination occurred.
     * @see com.bci.cmpp.Connection#BOUND
     * @see com.bci.cmpp.Connection#UNBOUND
     * @see com.bci.cmpp.Connection#BINDING
     * @see com.bci.cmpp.Connection#UNBINDING
     */
    public ReceiverExitEvent(Connection source, Throwable t, int state) {
        super(RECEIVER_EXIT, source);
        setException(t);
        this.connectionState = state;
    }

    /**
     * Test if this event represents an abnormal termination.
     * 
     * @return true if this event represents abnormal termination due to an
     *         exception, false if it represents normal termination.
     * @deprecated use {#link #getReason}
     */
    public boolean isException() {
        return (exception != null);
    }

    /**
     * Get the exception that caused termination.
     * 
     * @return the exception, or null if this event represents normal
     *         termination.
     */
    public Throwable getException() {
        return (exception);
    }

    public void setException(Throwable t) {
        this.exception = t;
        if (t != null) {
            this.reason = EXCEPTION;
        }
    }

    /**
     * Get the state the Connection was in when termination occurred.
     * 
     * @return the integer value representing the state of the connection.
     * @see com.bci.cmpp.Connection#BOUND
     * @see com.bci.cmpp.Connection#UNBOUND
     * @see com.bci.cmpp.Connection#BINDING
     * @see com.bci.cmpp.Connection#UNBINDING
     */
    public int getState() {
        return (connectionState);
    }

    /**
     * Get the reason for the exit event.
     * 
     * @return Returns the reason.
     */
    public int getReason() {
        return reason;
    }

    /**
     * Set the reason for the exit event. Should be one of the enumeration
     * values defined in this class.
     * 
     * @param reason
     *            The reason to set.
     */
    public void setReason(int reason) {
        this.reason = reason;
    }
}